package com.atguigu.tingshu.album.service.impl;

import com.atguigu.tingshu.album.mapper.AlbumAttributeValueMapper;
import com.atguigu.tingshu.album.mapper.AlbumInfoMapper;
import com.atguigu.tingshu.album.mapper.AlbumStatMapper;
import com.atguigu.tingshu.album.service.AlbumInfoService;
import com.atguigu.tingshu.common.cache.TsCache;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.rabbit.constant.MqConst;
import com.atguigu.tingshu.common.rabbit.service.RabbitService;
import com.atguigu.tingshu.model.album.AlbumAttributeValue;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.AlbumStat;
import com.atguigu.tingshu.query.album.AlbumInfoQuery;
import com.atguigu.tingshu.vo.album.AlbumAttributeValueVo;
import com.atguigu.tingshu.vo.album.AlbumInfoVo;
import com.atguigu.tingshu.vo.album.AlbumListVo;
import com.atguigu.tingshu.vo.album.AlbumStatVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.Nullable;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
@SuppressWarnings({"all"})
public class AlbumInfoServiceImpl extends ServiceImpl<AlbumInfoMapper, AlbumInfo> implements AlbumInfoService {

	@Autowired
	private AlbumInfoMapper albumInfoMapper;
	@Autowired
	private AlbumAttributeValueMapper albumAttributeValueMapper;
	@Autowired
	private AlbumStatMapper albumStatMapper;
	@Autowired
	private RabbitService rabbitService;
	@Autowired
	private RedisTemplate redisTemplate;
	@Autowired
	private RedissonClient redissonClient;


	/**
	 * 保存专辑信息
	 * @param albumInfoVo
	 * @param userId
	 */
	@Transactional(rollbackFor = Exception.class)
	@Override
	public void saveAlbumInfo(AlbumInfoVo albumInfoVo, Long userId) {
		//创建对象
		AlbumInfo albumInfo = new AlbumInfo();
		//赋值 拷贝
		BeanUtils.copyProperties(albumInfoVo,albumInfo);
		albumInfo.setUserId(userId);
		//付费类型
		if (!SystemConstant.ALBUM_PAY_TYPE_FREE.equals(albumInfoVo.getPayType())){
			//试集数
			albumInfo.setTracksForFree(5);
		}
		albumInfo.setStatus(SystemConstant.ALBUM_STATUS_PASS);
		//专辑信息
		albumInfoMapper.insert(albumInfo);
		//专辑属性值
		List<AlbumAttributeValueVo> albumAttributeValueVoList = albumInfoVo.getAlbumAttributeValueVoList();
		if (!CollectionUtils.isEmpty(albumAttributeValueVoList)) {
			for (AlbumAttributeValueVo albumAttributeValueVo : albumAttributeValueVoList) {
				//创建对象
				AlbumAttributeValue albumAttributeValue = new AlbumAttributeValue();
				//拷贝
				BeanUtils.copyProperties(albumAttributeValueVo, albumAttributeValue);
				albumAttributeValue.setAlbumId(albumInfo.getId());
				albumAttributeValueMapper.insert(albumAttributeValue);
			}
		}
		//统计类型
		this.saveStat(albumInfo.getId(),SystemConstant.ALBUM_STAT_PLAY);
		this.saveStat(albumInfo.getId(),SystemConstant.ALBUM_STAT_SUBSCRIBE);
		this.saveStat(albumInfo.getId(),SystemConstant.ALBUM_STAT_BROWSE);
		this.saveStat(albumInfo.getId(),SystemConstant.ALBUM_STAT_COMMENT);

		//判断是否上架
		if ("1".equals(albumInfoVo.getIsOpen())){
			rabbitService.sendMessage(MqConst.EXCHANGE_ALBUM, MqConst.ROUTING_ALBUM_UPPER, albumInfo.getId());
			//添加布隆过滤器
			RBloomFilter<Object> bloomFilter = redissonClient.getBloomFilter(RedisConstant.ALBUM_BLOOM_FILTER);
			bloomFilter.add(albumInfo.getId());
		}
	}

	public void saveStat(Long albumId, String albumStatBrowse) {
		//创建对象
		AlbumStat albumStat = new AlbumStat();
		albumStat.setAlbumId(albumId);
		albumStat.setStatType(albumStatBrowse);
		albumStat.setStatNum(new Random().nextInt(1000));
		//专辑统计
		albumStatMapper.insert(albumStat);
	}


	/**
	 * 查看专辑列表
	 * @param page
	 * @param albumInfoQuery
	 * @return
	 */
	@Override
	public IPage<AlbumListVo> findUserAlbumPage(AlbumInfoQuery albumInfoQuery, Page<AlbumListVo> page) {
		//	查询专辑列表： 专辑信息+专辑统计信息！
		return albumInfoMapper.selectUserAlbumPage(albumInfoQuery,page);
	}

	/**
	 * 删除专辑信息
	 * @param albumId
	 */
	@Override
	public void removeAlbumInfo(Long albumId) {
		//删除专辑信息
		albumInfoMapper.deleteById(albumId);
		//删除专辑属性值
		albumAttributeValueMapper.delete(new LambdaQueryWrapper<AlbumAttributeValue>().eq(AlbumAttributeValue::getAlbumId,albumId));
		//删除专辑统计
		albumStatMapper.delete(new LambdaQueryWrapper<AlbumStat>().eq(AlbumStat::getAlbumId,albumId));
		//下架
		rabbitService.sendMessage(MqConst.EXCHANGE_ALBUM,MqConst.ROUTING_ALBUM_LOWER,albumId);
	}

	/**
	 * 获取专辑信息
	 * @param albumId
	 * @return
	 */
	@Override
	@TsCache(prefix = RedisConstant.ALBUM_INFO_PREFIX)
	public AlbumInfo getAlbumInfo(Long albumId) {
		//return getAlbumInfoByRedisson(albumId);
		return getAlbumInfoDB(albumId);
	}

	@Nullable
	private AlbumInfo getAlbumInfoByRedisson(Long albumId) {
		//查询缓存
		String dataKey = RedisConstant.RANKING_KEY_PREFIX + albumId;
		try {
			//获取缓存中数据
			AlbumInfo albumInfo = (AlbumInfo) redisTemplate.opsForValue().get(dataKey);
			//判断缓存中数据是否为空
			if (albumInfo==null){
				//缓存为空从数据库查询 防止缓存击穿 加锁
				String lockKey = RedisConstant.ALBUM_LOCK_SUFFIX + albumId;
				RLock lock = redissonClient.getLock(lockKey);
				//加锁
				lock.lock();
				try {
					//从缓存中获取数据
					albumInfo = (AlbumInfo) redisTemplate.opsForValue().get(dataKey);
					if (albumInfo!=null){
						return albumInfo;
					}
					//从数据库查询
					albumInfo = getAlbumInfoDB(albumId);
					//判断albumInfo为空
					if (albumInfo==null){
						//设置空数据
						redisTemplate.opsForValue().set(dataKey,new AlbumInfo(),RedisConstant.ALBUM_TEMPORARY_TIMEOUT,TimeUnit.SECONDS);
						return new AlbumInfo();
					}
					//设置到缓存中
					redisTemplate.opsForValue().set(dataKey,albumInfo,RedisConstant.ALBUM_TIMEOUT, TimeUnit.MINUTES);
					return albumInfo;
				} finally {
					//解锁
					lock.unlock();
				}
			}else {
				return albumInfo;
			}
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
		return getAlbumInfoDB(albumId);
	}

	@Nullable
	private AlbumInfo getAlbumInfoDB(Long albumId) {
		//	创建对象
		AlbumInfo albumInfo = this.getById(albumId);
		//	判断
		if (null != albumInfo){
			albumInfo.setAlbumAttributeValueVoList(albumAttributeValueMapper.selectList(new LambdaQueryWrapper<AlbumAttributeValue>().eq(AlbumAttributeValue::getAlbumId, albumId)));
		}
		//	返回数据
		return albumInfo;
	}

	/**
	 * 修改专辑信息
	 * @param albumId
	 * @param albumInfoVo
	 */
	@Override
	public void updateAlbumInfo(Long albumId, AlbumInfoVo albumInfoVo) {
		//创建专辑对象
		AlbumInfo albumInfo = new AlbumInfo();
		//拷贝
		BeanUtils.copyProperties(albumInfoVo,albumInfo);
		//赋值
		albumInfo.setId(albumId);
		//修改专辑信息
		albumInfoMapper.updateById(albumInfo);
		//先删除旧数据 再新增
		albumAttributeValueMapper.delete(new LambdaQueryWrapper<AlbumAttributeValue>().eq(AlbumAttributeValue::getAlbumId,albumId));
		//获取属性值集合
		List<AlbumAttributeValueVo> albumAttributeValueVoList = albumInfoVo.getAlbumAttributeValueVoList();
		if (!CollectionUtils.isEmpty(albumAttributeValueVoList)){
			for (AlbumAttributeValueVo albumAttributeValueVo : albumAttributeValueVoList) {
				//创建对象
				AlbumAttributeValue albumAttributeValue = new AlbumAttributeValue();
				//赋值
				BeanUtils.copyProperties(albumAttributeValueVo,albumAttributeValue);
				albumAttributeValue.setAlbumId(albumId);
				albumAttributeValueMapper.insert(albumAttributeValue);
			}
		}
		//判断当前专辑是否上架
		if("1".equals(albumInfoVo.getIsOpen())){
			//上架
			rabbitService.sendMessage(MqConst.EXCHANGE_ALBUM,MqConst.ROUTING_ALBUM_UPPER,albumId);
			//添加布隆过滤器
			RBloomFilter<Object> bloomFilter = redissonClient.getBloomFilter(RedisConstant.ALBUM_BLOOM_FILTER);
			bloomFilter.add(albumInfo.getId());
		}else {
			//下架
			rabbitService.sendMessage(MqConst.EXCHANGE_ALBUM,MqConst.ROUTING_ALBUM_LOWER,albumId);
		}
	}


	/**
	 * 获取用户所有专辑信息
	 * @return
	 */
	@Override
	public List<AlbumInfo> findUserAllAlbumList() {
		//创建page
		Page<AlbumInfo> page = new Page<>(1,30);
		//排序
		LambdaQueryWrapper<AlbumInfo> albumInfoLambdaQueryWrapper = new LambdaQueryWrapper<AlbumInfo>().orderByDesc(AlbumInfo::getId);
		return albumInfoMapper.selectPage(page,albumInfoLambdaQueryWrapper).getRecords();
	}

	/**
	 * 获取专辑统计
	 * @param albumId
	 * @return
	 */
	@Override
	@TsCache(prefix = "album:stat")
	public AlbumStatVo getAlbumStatVo(Long albumId) {
		//	调用mapper 层方法
		return albumInfoMapper.selectAlbumStatVo(albumId);
	}

	/**
	 * 获取专辑属性值
	 * @param albumId
	 * @return
	 */
	@Override
	public List<AlbumAttributeValue> findAlbumAttributeValue(Long albumId) {
		LambdaQueryWrapper<AlbumAttributeValue> queryWrapper = new LambdaQueryWrapper<AlbumAttributeValue>().eq(AlbumAttributeValue::getAlbumId, albumId);
		List<AlbumAttributeValue> albumAttributeValues = albumAttributeValueMapper.selectList(queryWrapper);
		return albumAttributeValues;
	}
}
